package com.tin.triper.UI;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.tin.triper.Constants;
import com.tin.triper.R;
import com.tin.triper.Data.LocationProvider;
import com.tin.triper.Data.Resources;
import com.tin.triper.Data.TripOverlay;
import com.tin.triper.Data.TripPoint;
import com.tin.triper.Helper.Formating;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class PlayerActivity extends MapActivity {
	MapView mapView;
	SharedPreferences prefs;
	boolean isBound = false;
	Button buttonPlay;
	Button previousPoint;
	Button nextPoint;
	boolean playing = false;
	boolean isPaused = false;
	PlayerTask playerTask = null;
	private TextView longitude;
	private TextView latitude;
	private TextView speed;
	private MapController mapController;
	private List<Overlay> mapOverlays;
	private TextView time;
	private List<TripPoint> pointList = new ArrayList<TripPoint>();
	private List<Resources> resourcesList = new ArrayList<Resources>();
	public int currentPoint = 0;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.maps_player);

		mapView = (MapView) findViewById(R.id.mapview);
		mapView.setBuiltInZoomControls(true);
		buttonPlay = (Button) findViewById(R.id.player_play);
		previousPoint = (Button) findViewById(R.id.player_previous);
		nextPoint = (Button) findViewById(R.id.player_next);
		longitude = (TextView) findViewById(R.id.longitude);
		latitude = (TextView) findViewById(R.id.latitude);
		time = (TextView) findViewById(R.id.time);
		speed = (TextView) findViewById(R.id.speed);
		mapOverlays = mapView.getOverlays();
		mapController = mapView.getController();

		prefs = getSharedPreferences(Constants.PREFS_NAME, MODE_PRIVATE);
		drawTripPath(prefs.getInt(Constants.PLAYING_TRIP_ID, 0), mapView);
		mapController.animateTo(pointList.get(0));

		Date date = new Date();
		date.setTime(pointList.get(0).time);
		time.setText(getString(R.string.common_time) + ": "
				+ date.toLocaleString());
		longitude.setText(getString(R.string.common_longitude) + ": "
				+ pointList.get(0).getLongitudeE6() / 1E6 + "");
		latitude.setText(getString(R.string.common_latitude) + ": "
				+ pointList.get(0).getLatitudeE6() / 1E6 + "");
		speed.setText(getString(R.string.common_speed) + ": "
				+ Formating.countSpeed(pointList, currentPoint));

		buttonPlay.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View view) {
				Button bt = (Button) view;
				if (!playing) {
					if (currentPoint == pointList.size())
						currentPoint = 0;
					playerTask = new PlayerTask(mapView, pointList);
					playerTask.execute();
					bt.setText(getString(R.string.common_pause));
					playing = true;
					isPaused = false;
				} else {
					isPaused = true;
					bt.setText(getString(R.string.common_play));
					playing = false;
				}

			}
		});
		nextPoint.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				if (currentPoint < pointList.size() - 1) {
					currentPoint++;
					mapController.animateTo(pointList.get(currentPoint));
				} else {
					currentPoint = 0;
					mapController.animateTo(pointList.get(currentPoint));
				}
			}
		});
		previousPoint.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				if (currentPoint != 0) {
					currentPoint--;
					mapController.animateTo(pointList.get(currentPoint));
				} else {
					currentPoint = pointList.size() - 1;
					mapController.animateTo(pointList.get(currentPoint));
				}
			}
		});

	}

	@Override
	public void onBackPressed() {
		super.onBackPressed();
		finish();
	}

	public void drawTripPath(int tripId, MapView mapView) {
		mapView.getOverlays().clear();
		Cursor resourcesCursor = getContentResolver().query(
				LocationProvider.CONTENT_URI_RESOURCES,
				new String[] { LocationProvider.RESOURCE_ID,
						LocationProvider.LOCATION_ID,
						LocationProvider.RESOURCE_FILENAME,
						LocationProvider.RESOURCE_TYPE },
				LocationProvider.TRIP_ID + " ='" + tripId + "'", null, null);
		if (resourcesCursor != null)
			while (resourcesCursor.moveToNext()) {
				Resources res = new Resources();
				res.id = resourcesCursor.getInt(0);
				res.locationId = resourcesCursor.getInt(1);
				res.fileName = resourcesCursor.getString(2);
				res.type = resourcesCursor.getInt(3);
				resourcesList.add(res);
			}
		resourcesCursor.close();
		Cursor cursor = getContentResolver().query(
				LocationProvider.CONTENT_URI_LOCATION,
				new String[] { LocationProvider.LOCATION_LATITUDE,
						LocationProvider.LOCATION_LONGITUDE,
						LocationProvider.LOCATION_TIME,
						LocationProvider.LOCATION_ID },
				LocationProvider.TRIP_ID + " ='" + tripId + "'", null,
				LocationProvider.LOCATION_TIME);
		if (cursor != null)
			while (cursor.moveToNext()) {
				TripPoint point = new TripPoint(
						(int) (cursor.getDouble(0) * 1E6),
						(int) (cursor.getDouble(1) * 1E6), cursor.getLong(2),
						cursor.getInt(3));
				pointList.add(point);
			}
		cursor.close();
		Collections.sort(pointList, new TripComarable());
		drawPath(pointList, Color.parseColor("#0F08D3"), mapView);
		for (int i = 0; i < resourcesList.size(); i++)
			for (int l = 0; l < pointList.size(); l++) {
				if (resourcesList.get(i).locationId == pointList.get(l).id)
					pointList.get(l).gotResouce = true;
			}
		drawResources();

	}

	public class TripComarable implements Comparator<TripPoint> {

		@Override
		public int compare(TripPoint o1, TripPoint o2) {
			if (o1 == null)
				return -1;
			if (o2 == null)
				return 1;
			if (o1.time > o2.time)
				return 1;
			else
				return -1;
		}

	}

	private void drawResources() {
		for (int i = 0; i < resourcesList.size(); i++) {
			drawResoruce(resourcesList.get(i).locationId,
					resourcesList.get(i).type);
		}
	}

	private void drawResoruce(int locationId, int resourceType) {
		Bitmap resource = null;
		if (resourceType == 0) {
			resource = BitmapFactory.decodeResource(getResources(),
					R.drawable.text);
		} else if (resourceType == 1) {
			resource = BitmapFactory.decodeResource(getResources(),
					R.drawable.voice);
		} else if (resourceType == 2) {
			resource = BitmapFactory.decodeResource(getResources(),
					R.drawable.photo);
		} else {
			// video
			resource = BitmapFactory.decodeResource(getResources(),
					R.drawable.video);
		}
		if (resource != null) {
			for (int i = 0; i < pointList.size(); i++)
				if (pointList.get(i).id == locationId) {
					mapOverlays.add(new TripOverlay(pointList.get(i), 4,
							resource));
					break;
				}
		}
	}

	private void drawPath(final List<TripPoint> pointList, int color,
			MapView mapView) {
		try {
			GeoPoint startGP = new GeoPoint(pointList.get(0).getLatitudeE6(),
					pointList.get(0).getLongitudeE6());

			mapOverlays.add(new TripOverlay(startGP, startGP, 1));
			GeoPoint gp1 = startGP;
			GeoPoint gp2;
			gp2 = startGP;

			for (int i = 1; i < pointList.size(); i++) // the last one would be
														// crash
			{

				gp1 = gp2;

				if (pointList.size() >= 2) {
					gp2 = pointList.get(i);
					mapOverlays.add(new TripOverlay(gp1, gp2, 2, color));
					Log.d("mapview",
							"draw:" + gp1.getLatitudeE6() + "/"
									+ gp1.getLongitudeE6() + " TO "
									+ gp2.getLatitudeE6() + "/"
									+ gp2.getLongitudeE6());

				}
				Log.d("mapview", "pair:" + pointList.get(i));
			}
			mapOverlays.add(new TripOverlay(gp2, new GeoPoint(pointList.get(
					pointList.size() - 1).getLatitudeE6(), pointList.get(
					pointList.size() - 1).getLongitudeE6()), 3));
		} catch (NumberFormatException e) {
			Log.e("mapview", "Cannot draw route.", e);
		}
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.player_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection

		switch (item.getItemId()) {
		case R.id.player_change_speed:
			AlertDialog.Builder builder;

			LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
			View layout = inflater.inflate(R.layout.trip_time_delay,
					(ViewGroup) findViewById(R.id.trip_time_delay_layout));

			final SeekBar bar = (SeekBar) layout
					.findViewById(R.id.trip_time_delay_bar);
			final TextView textTime = (TextView) layout
					.findViewById(R.id.trip_time_delay_text);
			bar.setMax(3000);
			bar.setProgress((int) prefs.getLong(Constants.PLAYER_TRIP_DELAY,
					2000)-1000);
			textTime.setText(prefs.getLong(Constants.PLAYER_TRIP_DELAY, 2000)
					+ " " + getString(R.string.date_seconds));
			bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

				@Override
				public void onStopTrackingTouch(SeekBar arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void onStartTrackingTouch(SeekBar arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void onProgressChanged(SeekBar arg0, int arg1,
						boolean arg2) {
					textTime.setText(bar.getProgress()+1000 + " "
							+ getString(R.string.date_seconds));
				}
			});
			builder = new AlertDialog.Builder(PlayerActivity.this);
			builder.setView(layout);
			builder.setNeutralButton(getString(R.string.common_ok),
					new DialogInterface.OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {
							prefs.edit()
									.putLong(Constants.PLAYER_TRIP_DELAY,
											bar.getProgress()+1000).commit();
						}

					});
			builder.create().show();
			return true;

		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private class PlayerTask extends AsyncTask<Void, Void, Boolean> {
		private MapView mapView;
		private List<TripPoint> pointList;

		public PlayerTask(MapView mapView, List<TripPoint> pointList) {
			this.mapView = mapView;
			this.pointList = pointList;
		}

		protected Boolean doInBackground(Void... urls) {
			for (; currentPoint < pointList.size(); currentPoint++) {
				if (isPaused)
					return false;
				publishProgress();
				if (pointList.get(currentPoint).gotResouce) {
					isPaused = true;

					return true;
				}
				try {
					Thread.sleep(prefs.getLong(Constants.PLAYER_TRIP_DELAY,
							2000));
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return false;
		}

		protected void onProgressUpdate(Void... progress) {
			mapView.getController().animateTo(pointList.get(currentPoint));
			Date date = new Date();
			SimpleDateFormat formatter = new SimpleDateFormat(
					"yyyy.MM.dd 'at' H:mm:ss ");

			date.setTime(pointList.get(currentPoint).time);
			time.setText(getString(R.string.common_time) + ": "
					+ formatter.format(date));
			longitude.setText(getString(R.string.common_longitude) + ": "
					+ pointList.get(currentPoint).getLongitudeE6() / 1E6 + "");
			latitude.setText(getString(R.string.common_latitude) + ": "
					+ pointList.get(currentPoint).getLatitudeE6() / 1E6 + "");
			speed.setText(getString(R.string.common_speed) + ": "
					+ Formating.countSpeed(pointList, currentPoint));
		}

		protected void onPostExecute(Boolean result) {
			if (!result) {
				buttonPlay.setText(getString(R.string.common_play));
				playing = false;
			} else {
				for (int i = 0; i < resourcesList.size(); i++)
					if (pointList.get(currentPoint).id == resourcesList.get(i).locationId) {
						if (resourcesList.get(i).type == 0) {
							Intent intent = new Intent(PlayerActivity.this,
									TextActivity.class);
							intent.putExtra(Constants.ACTIVITY_MODE, 2);
							intent.putExtra(Constants.RESOURCE_ID,
									resourcesList.get(i).id);
							intent.putExtra(Constants.TRIP_ID,
									prefs.getInt(Constants.PLAYING_TRIP_ID, 0));
							intent.putExtra(Constants.TRIP_NAME, prefs
									.getString(Constants.PLAYING_TRIP_NAME, ""));
							startActivityForResult(intent,
									Constants.TEXT_ACTIVITY);
							break;
						} else if (resourcesList.get(i).type == 1) {
							Intent intent = new Intent(PlayerActivity.this,
									VoiceActivity.class);
							intent.putExtra(Constants.ACTIVITY_MODE, 2);
							intent.putExtra(Constants.RESOURCE_ID,
									resourcesList.get(i).id);
							intent.putExtra(Constants.TRIP_ID,
									prefs.getInt(Constants.PLAYING_TRIP_ID, 0));
							intent.putExtra(Constants.TRIP_NAME, prefs
									.getString(Constants.PLAYING_TRIP_NAME, ""));
							startActivityForResult(intent,
									Constants.TEXT_ACTIVITY);
							break;
						} else if (resourcesList.get(i).type == 2) {
							Intent intent = new Intent(PlayerActivity.this,
									ImageActivity.class);
							intent.putExtra(Constants.ACTIVITY_MODE, 2);
							intent.putExtra(Constants.RESOURCE_ID,
									resourcesList.get(i).id);
							intent.putExtra(Constants.TRIP_ID,
									prefs.getInt(Constants.PLAYING_TRIP_ID, 0));
							intent.putExtra(Constants.TRIP_NAME, prefs
									.getString(Constants.PLAYING_TRIP_NAME, ""));
							startActivityForResult(intent,
									Constants.TEXT_ACTIVITY);
							break;
						} else if (resourcesList.get(i).type == 3) {
							Intent intent = new Intent(PlayerActivity.this,
									VideoActivity.class);
							intent.putExtra(Constants.ACTIVITY_MODE, 2);
							intent.putExtra(Constants.RESOURCE_ID,
									resourcesList.get(i).id);
							intent.putExtra(Constants.TRIP_ID,
									prefs.getInt(Constants.PLAYING_TRIP_ID, 0));
							intent.putExtra(Constants.TRIP_NAME, prefs
									.getString(Constants.PLAYING_TRIP_NAME, ""));
							startActivityForResult(intent,
									Constants.TEXT_ACTIVITY);
							break;
						}
					}
			}

		}
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == Constants.TEXT_ACTIVITY
				|| requestCode == Constants.VOICE_ACTIVITY
				|| requestCode == Constants.VIDEO_ACTIVITY
				|| requestCode == Constants.IMAGE_ACTIVITY) {
			if (currentPoint == pointList.size())
				return;
			currentPoint++;
			playerTask = new PlayerTask(mapView, pointList);
			playerTask.execute();
			buttonPlay.setText(getString(R.string.common_pause));
			playing = true;
			isPaused = false;
		}

	}

}
